using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using System.Reflection;
using UnityEngine;

namespace EchoFramework
{
    /// <summary>
    /// 配置表管理器
    /// </summary>
    /// <typeparam name="T">目标Config类型</typeparam>
    public class ConfigManager<T> where T : Config, new()
    {
        /// <summary>
        /// 是否初始化
        /// </summary>
        private bool isInit;

        /// <summary>
        /// 当前配置表的字典
        /// key:ID
        /// value:T
        /// </summary>
        protected Dictionary<int, T> dict = new Dictionary<int, T>();

        /// <summary>
        /// 当前配置表的列表
        /// </summary>
        protected List<T> list;

        private static ConfigManager<T> instance;

        public static ConfigManager<T> Instance
        {
            get
            {
                if (instance == null)
                    instance = new ConfigManager<T>();
                return instance;
            }
        }

        /// <summary>
        /// 通过ID，返回对应配置表数据
        /// </summary>
        /// <param name="ID">配置表ID</param>
        /// <returns>配置表实例</returns>
        public T GetData(int ID)
        {
            InternalInit();

            if (dict.TryGetValue(ID, out T retCofig))
            {
                return retCofig;
            }
            else
            {
                GameLogger.LogError(string.Format("{0} 中未找到ID:{1}的配置", typeof(T).Name, ID));
                return null;
            }
        }

        /// <summary>
        /// 返回整个配置表字典
        /// </summary>
        /// <returns>配置表实例</returns>
        public Dictionary<int, T> GetData()
        {
            InternalInit();

            return dict;
        }

        /// <summary>
        /// 返回整个配置表List
        /// </summary>
        /// <returns>配置表实例列表</returns>
        public List<T> GetDataList()
        {
            InternalInit();

            if (list == null)
            {
                list = new List<T>();
                foreach (var cfg in dict)
                {
                    list.Add(cfg.Value);
                }
            }

            return list;
        }

        /// <summary>
        /// 初始化配置表
        /// </summary>
        private void InternalInit()
        {
            if (!isInit)
            {
                ParseXmlToConfigDic();
                isInit = true;
            }
        }


        /// <summary>
        /// Xml解析为Config字典
        /// </summary>
        private void ParseXmlToConfigDic()
        {
            string typeName = typeof(T).Name;
            // string fullTypeName = string.Format("{0}.{1}", Assembly.GetExecutingAssembly().GetName().Name, typeName);
            string fullTypeName = typeName;
            if (fullTypeName.Equals("UIViewCfg"))
            {
                fullTypeName = "EchoFramework.UIViewCfg";
            }
            Type type = Type.GetType(fullTypeName);

            string path = $"Assets/GameRes/Config/{typeof(T).Name}.xml";
            XDocument xDoc = null;
            if (GameEntry.Instance.AssetBundleMode)
            {
                TextAsset ta = AssetManager.Instance.LoadAsset<TextAsset>(path, GameEntry.Instance.gameObject, false);
                xDoc = XDocument.Parse(ta.text);
            }
            else
            {
                try
                {
                    xDoc = XDocument.Load(path);
                }
                catch (Exception)
                {
                    GameLogger.LogError("找不到xml文件：" + path);
                }
            }

            if (xDoc == null)
            {
                GameLogger.LogError(typeName + "得到的XDocument为null！！！");
                return;
            }

            XElement rootEle = xDoc.Root;
            foreach (var ele in rootEle.Elements())
            {
                T typeInstance = type.Assembly.CreateInstance(fullTypeName) as T;

                for (int i = 0; i < type.GetFields().Length; i++)
                {
                    FieldInfo fi = type.GetFields()[i];

                    //保证配置字段有ConfigMark变量
                    ConfigMarkAttribute configMark =
                        (ConfigMarkAttribute) Attribute.GetCustomAttribute(fi, typeof(ConfigMarkAttribute));
                    if (configMark == null)
                        continue;

                    //保证为只读
                    if (!fi.IsInitOnly)
                        continue;

                    string strValue = ele.Attribute(fi.Name).Value;
                    if (fi.FieldType.Name.Contains("[]")) //数组类型
                    {
                        fi.SetValue(typeInstance, Str2BaseAryTypeValue(strValue, fi.FieldType));
                    }
                    else //基础类型
                    {
                        fi.SetValue(typeInstance, Str2BaseTypeValue(strValue, fi.FieldType));
                    }
                }

                dict.Add(typeInstance.ID, typeInstance);
            }
        }

        /// <summary>
        /// 将字符串转换为基础类型的值
        /// </summary>
        private object Str2BaseTypeValue(string str, Type type)
        {
            if (str == "" && type.Name == "Boolean")
                return bool.Parse("false");
            if (str == "" && type.Name != "String")
                return 0;
            switch (type.Name)
            {
                case "String":
                    return str;
                case "Int32":
                    return int.Parse(str);
                case "Int64":
                    return long.Parse(str);
                case "Single":
                    return float.Parse(str);
                case "Double":
                    return double.Parse(str);
                case "Boolean":
                    int ret = Convert.ToInt32(str);
                    str = ret > 0 ? "true" : "false";
                    return bool.Parse(str);
                default:
                    Debug.LogError(string.Format("配置表不能解析{0}类型，导入错误！", type.Name));
                    return null;
            }
        }

        /// <summary>
        /// 将字符串转换为基础数组类型的值
        /// </summary>
        private object Str2BaseAryTypeValue(string str, Type type)
        {
            //一维数组
            if (type.Name.Contains("[]"))
            {
                string[] arg1 = str.Split(',');
                Type tt1 = type.GetElementType();
                Array cfgArg1 = Array.CreateInstance(tt1, arg1.Length);
                for (int i = 0; i < arg1.Length; i++)
                {
                    cfgArg1.SetValue(Str2BaseTypeValue(arg1[i], tt1), i);
                }

                return cfgArg1;
            }

            Debug.LogError(string.Format("数组解析异常，无法解析{0}，读取配置表失败！", type.Name));
            return null;
        }
    }
}